﻿using Sttplay.Transmission.SerialPortEx;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace transmission
{
    public class SerialPortContext : Context
    {
        public string COM;
        public int buardRate;
        public Parity parity;
        public int dataBits;
        public StopBits stopBits;
        public bool DTR, RTS;
        private SerialPortEx serialPort = new SerialPortEx();
        private TreeViewItem treeItem;
        private StackPanelEx stack;
        private Image icon = new Image();
        public SolidColorBrush StateColor { get; private set; }

        public SerialPortContext()
        {
            serialPort.OnReceiveEvent += OnRecv;
        }

        public void Init()
        {
            treeItem = new TreeViewItem();
            treeItem.IsExpanded = true;
            stack = new StackPanelEx();
            stack.Orientation = Orientation.Horizontal;
            treeItem.Header = stack;

           
            icon.VerticalAlignment = VerticalAlignment.Center;
            icon.Height = 15;
            icon.Width = 15;
            icon.Margin = new Thickness(0, 0, 4, 0);

            stack.Children.Add(icon);
            TextBlock textBlock = new TextBlock();
            textBlock.VerticalAlignment = VerticalAlignment.Center;
            
            textBlock.Text = string.Format("{0}:{1}", COM, buardRate);

            stack.Children.Add(textBlock);
            stack.user = this;
            stack.type = TransmissionType.SerialPort;
            treeItem.IsSelected = true;
        }

        public bool Open()
        {
            serialPort.DTR = DTR;
            serialPort.RTS = RTS;
            if(!serialPort.Open(COM, buardRate, parity, dataBits, stopBits))
            {
                Close();
                return false;
            }
            StateColor = new SolidColorBrush(Color.FromRgb(20, 255, 0));
            icon.Source = new BitmapImage(new Uri("pack://application:,,,/res/serialport_run.png"));
            return true;
        }

        public void Close()
        {
            StateColor = Brushes.Gray;
            icon.Source = new BitmapImage(new Uri("pack://application:,,,/res/serialport_stop.png"));
            serialPort.Close();
        }

        public TreeViewItem GetTreeViewItem()
        {
            return treeItem;
        }

        public override void Tick()
        {
            if (!needUpdateUI) return;
            needUpdateUI = false;
            RecvText = string.Join("\n", recvList.ToArray());
            MainWindow.Instance.UpdateContextText(this);
        }
        public override void Update()
        {
            base.Update();
            serialPort.Update();
        }

        private void OnRecv(byte[] buffer)
        {
            string msg = GetRecvBuffer(buffer);
            OnRecvImp(msg, "接收");
        }

        private void OnRecvImp(string msg, string extend)
        {
            recvList.Add(string.Format("[{0} {1}] {2}", DateTime.Now.ToString("HH:mm:ss"), extend, msg));
            while (recvList.Count > MAX_SHOW_LINE)
                recvList.RemoveAt(0);
            RecvText = string.Join("\n", recvList.ToArray());
            needUpdateUI = true;
        }


        public override void Send()
        {
            string str;
            byte[] bs = GetSendBuffer(out str);
            if (bs == null)
                return;

            serialPort.Write(bs);
            OnRecvImp(str, "发送");
        }

        private string lastCalcStr = "";
        public override void Trigger()
        {
            if (lastCalcStr == SendText.Trim()) return;
            string str;
            byte[] bs = GetSendBuffer(out str);
            if (bs == null) return;
            if (!HexMode) return;
            byte[] verify = Verify(bs, 0, bs.Length, VerifyType.CRC_16);
            string verifyStr = " ";
            for (int i = 0; i < verify.Length; i++)
                verifyStr += Convert.ToString(verify[i], 16).PadLeft(2, '0') + " ";
            verifyStr = verifyStr.TrimEnd(' ');
            lastCalcStr = SendText + verifyStr;
            MainWindow.Instance.sendText.Text = lastCalcStr;
            MainWindow.Instance.sendText.SelectionStart = int.MaxValue;
        }
    }
}
